package cn.gaaidou.dynamic.proxy.cglib;

import cn.gaaidou.dynamic.proxy.cglib.annotation.SystemLog;
import cn.gaaidou.dynamic.proxy.cglib.callback.SystemLogCallback;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Optional;

/**
 * @author Martin
 * @date 2021/7/14 16:10
 */
@Slf4j
public class BeanFactory {

    static {
        // 生成代理类的class文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\code");
    }

    /**
     * 根据class创建Bean
     * 1、如果该Bean有SystemLog注解, 则生成cglib代理对象
     * 2、如果该Bean没有SystemLog注解
     *
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<T> clazz) {
        // 1、判断是否存在SystemLog对象
        boolean isProxy = Arrays.stream(clazz.getMethods()).anyMatch(v -> null != v.getAnnotation(SystemLog.class));
        if (isProxy) {
            // 2、创建Cglib对象
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(new SystemLogCallback());
            return (T) enhancer.create();
        } else {
            // 3、生成原对象
            Optional<Constructor<?>> noArgsConstructor = Arrays.stream(clazz.getConstructors()).filter(v -> v.getParameterCount() == 0).findFirst();
            try {
                if (noArgsConstructor.isPresent()) {
                    return (T) noArgsConstructor.get().newInstance();
                } else {
                    return clazz.newInstance();
                }
            } catch (Exception e) {
                log.error("创建对象 {} 失败", clazz.getName());
                throw new RuntimeException("创建对象失败");
            }
        }
    }
}
